#include "media_snap_manager.h"

#include "base_log.h"
#include "camera_video_enc.h"
#include <memory>

namespace El {
namespace Media {

ISnap &ISnap::GetInstance(uint32_t ch, int32_t type)
{
    static std::map<std::pair<uint32_t, int32_t>, SnapManager *> instances;
    static std::mutex mutex;

    std::lock_guard<std::mutex> lock(mutex);
    auto key = std::make_pair(ch, type);
    auto it = instances.find(key);
    if (it == instances.end()) {
        SnapManager *instance = new SnapManager(ch, type);
        instances.emplace(key, instance);
        return *instance;
    }
    return *it->second;
}

SnapManager::SnapManager(uint32_t ch, int32_t type) : ch_(ch), type_(type) {}

bool SnapManager::Start()
{
    if (isStarted_) {
        LOG_INFO("Snap module already started, channel: {}, type: {}", ch_, type_);
        return true;
    }

    LOG_INFO("Start snap module, channel: {}, type: {}", ch_, type_);

    // 获取抓图通道实例
    auto &camera = Hal::ICameraVideoEnc::GetInstance(ch_, type_);

    // 注册抓图回调
    handle_ = camera.Start([this](const VideoEncPacket &packet) {
        if (packet.frameType == MEDIA_FRAME_JPEG) {
            LOG_DEBUG("Received snapshot: size={}, width={}, height={}", packet.len, packet.width, packet.height);

            auto media = std::make_shared<MediaFrame>();
            if (!media->PutBuffer(packet.buf, packet.len)) {
                LOG_ERROR("Failed to put buffer");
                return;
            }
            media->SetPts(packet.pts);
            media->SetUtc(packet.utc);
            media->SetFrameType(packet.frameType);
            media->SetCodecType(packet.codecType);

            callbackManager_.InvokeAll(media);
        }
    });

    if (handle_ < 0) {
        LOG_ERROR("Failed to start snapshot");
        return false;
    }

    isStarted_ = true;
    return true;
}

void SnapManager::Stop()
{
    if (!isStarted_) {
        LOG_INFO("Snap module already stopped, channel: {}, type: {}", ch_, type_);
        return;
    }

    LOG_INFO("Stop snap module");

    // 获取抓图通道实例
    auto &camera = Hal::ICameraVideoEnc::GetInstance(ch_, type_);

    // 停止抓图
    camera.Stop(handle_);

    isStarted_ = false;
}

int32_t SnapManager::Register(const Proc &proc)
{
    return callbackManager_.Register(proc);
}

void SnapManager::Unregister(int32_t handle)
{
    callbackManager_.Unregister(handle);
}

bool SnapManager::ManualSnap()
{
    LOG_DEBUG("Manual snap, channel: {}, type: {}", ch_, type_);

    // 获取抓图通道实例
    auto &camera = Hal::ICameraVideoEnc::GetInstance(ch_, type_);

    // 触发抓图
    if (camera.Snapshot() != 0) {
        LOG_ERROR("Failed to trigger snapshot");
        return false;
    }
    return true;
}

} // namespace Media
} // namespace El
